/**
 *
 */
package org.etlt.expression.op.define;

import org.etlt.expression.IllegalExpressionException;
import org.etlt.expression.datameta.BaseDataMeta;
import org.etlt.expression.datameta.Literal;
import org.etlt.expression.datameta.Reference;
import org.etlt.expression.op.IOperatorExecution;
import org.etlt.expression.op.Operator;

import java.math.BigDecimal;
import java.util.Objects;

/**
 * 逻辑等于操作
 * @version 2.0
 */
public class Op_EQ implements IOperatorExecution {

    public static final Operator THIS_OPERATOR = Operator.EQ;


    public Literal execute(Literal[] args) throws IllegalExpressionException {

        if (args == null || args.length != 2) {
            throw new IllegalArgumentException("操作符\"" + THIS_OPERATOR.getToken() + "参数个数不匹配");
        }

        Literal first = args[1];
        Literal second = args[0];
        if (first == null || second == null) {
            throw new NullPointerException("操作符\"" + THIS_OPERATOR.getToken() + "\"参数为空");
        }

        //如果第一参数为引用，则执行引用
        if (first.isReference()) {
            Reference firstRef = (Reference) first.getDataValue();
            first = firstRef.execute();
        }
        //如果第二参数为引用，则执行引用
        if (second.isReference()) {
            Reference secondRef = (Reference) second.getDataValue();
            second = secondRef.execute();
        }

        //集合类型EQ运算单独处理
        if (BaseDataMeta.DataType.DATATYPE_LIST == first.getDataType()
                || BaseDataMeta.DataType.DATATYPE_LIST == second.getDataType()) {
            //目前不支持集合EQ比较，
            throw new IllegalArgumentException("操作符\"" + THIS_OPERATOR.getToken() + "\"参数类型错误");
        }
        if(first.getDataType().isCompatible(second.getDataType()) ||
            second.getDataType().isCompatible(first.getDataType())){
            if(first.getDataType().isDecimal() || second.getDataType().isDecimal()){
                BigDecimal firstDecimal = first.getDecimalValue();
                BigDecimal secondDecimal = second.getDecimalValue();
                if(firstDecimal.equals(secondDecimal))
                    return new Literal(BaseDataMeta.DataType.DATATYPE_BOOLEAN, Boolean.TRUE);
                return new Literal(BaseDataMeta.DataType.DATATYPE_BOOLEAN, Boolean.FALSE);
            }
            if(Objects.equals(first.getDataValue(), second.getDataValue()))
                return new Literal(BaseDataMeta.DataType.DATATYPE_BOOLEAN, Boolean.TRUE);
            return new Literal(BaseDataMeta.DataType.DATATYPE_BOOLEAN, Boolean.FALSE);
        }else {
                //如果操作数没有NULL型，且类型不同，抛异常（如果有校验，校验时就应该抛异常）
                throw new IllegalArgumentException("操作符\"" + THIS_OPERATOR.getToken() + "\"参数类型错误");
        }

    }


    public Literal verify(int opPosition, BaseDataMeta[] args)
            throws IllegalExpressionException {

        if (args == null || args.length != 2) {
            //抛异常
            throw new IllegalExpressionException("操作符\"" + THIS_OPERATOR.getToken() + "\"参数个数不匹配"
                    , THIS_OPERATOR.getToken()
                    , opPosition
            );
        }
        BaseDataMeta first = args[1];
        BaseDataMeta second = args[0];

        //集合类型EQ运算单独处理
        if (BaseDataMeta.DataType.DATATYPE_LIST == first.getDataType()
                || BaseDataMeta.DataType.DATATYPE_LIST == second.getDataType()) {
            //不支持集合EQ比较
            throw new IllegalExpressionException("操作符\"" + THIS_OPERATOR.getToken() + "\"参数类型错误"
                    , THIS_OPERATOR.getToken()
                    , opPosition);

        }
        if (first.getDataType().isCompatible(second.getDataType())
                || second.getDataType().isCompatible(first.getDataType())) {
            return new Literal(BaseDataMeta.DataType.DATATYPE_BOOLEAN, Boolean.FALSE);
        } else {
            //抛异常
            throw new IllegalExpressionException("操作符\"" + THIS_OPERATOR.getToken() + "\"参数类型错误"
                    , THIS_OPERATOR.getToken()
                    , opPosition);
        }
    }
}
